package yt.spider.activity;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.victor.loading.rotate.RotateLoading;

import org.greenrobot.eventbus.EventBus;
import org.mozilla.universalchardet.UniversalDetector;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import yt.spider.R;
import yt.spider.SimpleObserver;
import yt.spider.adapter.ImportBookAdapter;
import yt.spider.bean.BookInfoBeanDao;
import yt.spider.bean.BookShelfBean;
import yt.spider.bean.ChapterListBean;
import yt.spider.bean.ChapterListBeanDao;
import yt.spider.bean.LocBookShelfBean;
import yt.spider.dao.DbHelper;
import yt.spider.events.MessageEvent;
import yt.spider.help.BookshelfHelp;
import yt.spider.help.FormatWebText;
import yt.spider.utils.PremissionCheck;
import yt.spider.view.MoProgressHUD;

/**
 * Created by songyuanjin on 2018/4/8.
 */

public class ImportBookActivity extends BaseActivity {
    private final int RESULT_CHOOSE_DIRECTORY = 1;
    @BindView(R.id.toolbar)
    Toolbar toolbar;
    @BindView(R.id.ll_content)
    LinearLayout llContent;
    @BindView(R.id.tv_scan)
    TextView tvScan;
    @BindView(R.id.rl_loading)
    RotateLoading rlLoading;
    @BindView(R.id.tv_count)
    TextView tvCount;
    @BindView(R.id.rcv_books)
    RecyclerView rcvBooks;
    @BindView(R.id.tv_select_dir)
    TextView tvSelectDir;
    @BindView(R.id.ll_scan)
    LinearLayout llScan;

    private MoProgressHUD moProgressHUD;

    private ImportBookAdapter importBookAdapter;
    private MenuItem menuItem;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_book_import);
        ButterKnife.bind(this);
        initData();
        setupActionBar();
        moProgressHUD = new MoProgressHUD(this);

        rcvBooks.setAdapter(importBookAdapter);
        rcvBooks.setLayoutManager(new LinearLayoutManager(this));

        setEvents();
    }

    public void setEvents() {
        tvScan.setOnClickListener(v -> {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PremissionCheck.checkPremission(ImportBookActivity.this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                //申请权限
                ImportBookActivity.this.requestPermissions(
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        0x11);
            } else {
                searchLocationBook(new File(Environment.getExternalStorageDirectory().getAbsolutePath()));
                llScan.setVisibility(View.INVISIBLE);
                rlLoading.start();
            }
        });
        tvSelectDir.setOnClickListener(view -> {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !PremissionCheck.checkPremission(ImportBookActivity.this,
                    Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                //申请权限
                ImportBookActivity.this.requestPermissions(
                        new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
                        0x11);
            } else {
                if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
                    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
                    intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
                    startActivityForResult(intent, RESULT_CHOOSE_DIRECTORY);
                } else {
                    Toast.makeText(this, "当前系统版本不支持", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

    //设置ToolBar
    private void setupActionBar() {
        this.setSupportActionBar(toolbar);
        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setTitle(R.string.book_local);
        }
    }

    protected void initData() {
        importBookAdapter = new ImportBookAdapter(count -> {
            if (menuItem != null) {
                menuItem.setVisible(count != 0);
            }
        });
    }

    public void searchLocationBook(final File file) {
        Observable.create(new ObservableOnSubscribe<File>() {
            @Override
            public void subscribe(ObservableEmitter<File> e) throws Exception {
                if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    searchBook(e, file);
                }
                e.onComplete();
            }
        }).observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(new Observer<File>() {
                    @Override
                    public void onSubscribe(Disposable d) {

                    }

                    @Override
                    public void onNext(File file) {
                        addNewBook(file);
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                    }

                    @Override
                    public void onComplete() {
                        searchFinish();
                    }
                });


    }

    private void searchBook(ObservableEmitter<File> e, File parentFile) {
        if (null != parentFile && parentFile.listFiles().length > 0) {
            File[] childFiles = parentFile.listFiles();
            for (File childFile : childFiles) {
                if (childFile.isFile()
                        && childFile.getName().substring(childFile.getName().lastIndexOf(".") + 1).equalsIgnoreCase("txt")
                        && childFile.length() > 100 * 1024) {   //100kb
                    e.onNext(childFile);
                    continue;
                }
                if (childFile.isDirectory() && childFile.listFiles().length > 0) {
                    searchBook(e, childFile);
                }
            }
        }
    }

    public void searchFinish() {
        rlLoading.stop();
        rlLoading.setVisibility(View.INVISIBLE);
        importBookAdapter.setCanCheck(true);
    }

    public void addError() {
        moProgressHUD.showInfo("放入书架失败!");
    }

    public void addSuccess() {
        EventBus.getDefault().post(new MessageEvent());
        moProgressHUD.dismiss();
        Toast.makeText(this, "添加书籍成功", Toast.LENGTH_SHORT).show();
    }

    // 添加菜单
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_book_import, menu);
        return super.onCreateOptionsMenu(menu);
    }

    //菜单状态
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        menuItem = menu.getItem(0);
        menuItem.setVisible(false);
        return super.onPrepareOptionsMenu(menu);
    }

    //菜单
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id) {
            case R.id.action_import_book:
                //添加书籍
                moProgressHUD.showLoading("放入书架中...");
                importBooks(importBookAdapter.getSelectDatas());
                //mPresenter.importBooks(importBookAdapter.getSelectDatas());
                break;
            case android.R.id.home:
                finish();
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    public void importBooks(List<File> books) {
        Observable.fromIterable(books).flatMap(file -> importNewBook(file))
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new SimpleObserver<LocBookShelfBean>() {
                    @Override
                    public void onNext(LocBookShelfBean value) {
                        if (value.getNew()) {
                            //RxBus.get().post(RxBusTag.HAD_ADD_BOOK, value.getBookShelfBean());
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        addError();
                    }

                    @Override
                    public void onComplete() {
                        addSuccess();
                    }
                });
    }

    public void addNewBook(File newFile) {
        importBookAdapter.addData(newFile);
        tvCount.setText(String.format(getString(R.string.import_books_count), String.valueOf(importBookAdapter.getItemCount())));
    }

    @SuppressLint("NewApi")
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == 0x11) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && PremissionCheck.checkPremission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                //mPresenter.searchLocationBook(new File(Environment.getExternalStorageDirectory().getAbsolutePath()));
                llScan.setVisibility(View.INVISIBLE);
                rlLoading.start();
            } else {
                if (!this.shouldShowRequestPermissionRationale(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
                    moProgressHUD.showTwoButton("去系统设置打开SD卡读写权限？", "取消", v -> moProgressHUD.dismiss(), "设置", v -> {
                        moProgressHUD.dismiss();
                        PremissionCheck.requestPermissionSetting(ImportBookActivity.this);
                    });
                } else {
                    Toast.makeText(this, "未获取SD卡读取权限", Toast.LENGTH_SHORT).show();
                }
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }


    public Observable<LocBookShelfBean> importNewBook(final File book) {
        return Observable.create(e -> {
            MessageDigest md = MessageDigest.getInstance("MD5");
            FileInputStream in = new FileInputStream(book);
            byte[] buffer = new byte[2048];
            int len;
            while ((len = in.read(buffer, 0, 2048)) != -1) {
                md.update(buffer, 0, len);
            }
            in.close();

            String md5 = new BigInteger(1, md.digest()).toString(16);
            BookShelfBean bookShelfBean;
            bookShelfBean = BookshelfHelp.getBook(md5);
            Boolean isNew = true;
            if (bookShelfBean != null) {
                isNew = false;
                bookShelfBean.setBookInfoBean(DbHelper.getInstance().getmDaoSession().getBookInfoBeanDao().queryBuilder().where(BookInfoBeanDao.Properties.NoteUrl.eq(bookShelfBean.getNoteUrl())).build().list().get(0));
            } else {
                bookShelfBean = new BookShelfBean();
                bookShelfBean.setFinalDate(System.currentTimeMillis());
                bookShelfBean.setDurChapter(0);
                bookShelfBean.setDurChapterPage(0);
                bookShelfBean.setTag(BookShelfBean.LOCAL_TAG);
                bookShelfBean.setNoteUrl(md5);

                bookShelfBean.getBookInfoBean().setAuthor("佚名");
                bookShelfBean.getBookInfoBean().setName(book.getName().replace(".txt", "").replace(".TXT", ""));
                bookShelfBean.getBookInfoBean().setFinalRefreshData(System.currentTimeMillis());
                bookShelfBean.getBookInfoBean().setCoverUrl("");
                bookShelfBean.getBookInfoBean().setNoteUrl(md5);
                bookShelfBean.getBookInfoBean().setTag(BookShelfBean.LOCAL_TAG);
                saveChapter(book, md5);
                DbHelper.getInstance().getmDaoSession().getBookInfoBeanDao().insertOrReplace(bookShelfBean.getBookInfoBean());
                DbHelper.getInstance().getmDaoSession().getBookShelfBeanDao().insertOrReplace(bookShelfBean);
            }
            bookShelfBean.getBookInfoBean().setChapterList(DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().queryBuilder().where(ChapterListBeanDao.Properties.NoteUrl.eq(bookShelfBean.getNoteUrl())).orderAsc(ChapterListBeanDao.Properties.DurChapterIndex).build().list());
            e.onNext(new LocBookShelfBean(isNew, bookShelfBean));
            e.onComplete();
        });
    }


    private void saveChapter(File book, String md5) throws IOException {
        String regex = "第.{1,7}章.{0,}";
        String encoding;
        FileInputStream fis = new FileInputStream(book);
        byte[] buf = new byte[4096];
        UniversalDetector detector = new UniversalDetector(null);
        int nread;
        while ((nread = fis.read(buf)) > 0 && !detector.isDone()) {
            detector.handleData(buf, 0, nread);
        }
        detector.dataEnd();
        encoding = detector.getDetectedCharset();
        if (encoding == null || encoding.length() == 0)
            encoding = "utf-8";
        fis.close();

        int chapterPageIndex = 0;
        String title = null;
        StringBuilder contentBuilder = new StringBuilder();
        fis = new FileInputStream(book);
        InputStreamReader inputreader = new InputStreamReader(fis, encoding);
        BufferedReader buffreader = new BufferedReader(inputreader);
        String line;
        while ((line = buffreader.readLine()) != null) {
            line = FormatWebText.getContent(line);
            Pattern p = Pattern.compile(regex);
            Matcher m = p.matcher(line);
            if (m.find()) {
                String temp = line.trim().substring(0, line.trim().indexOf("第"));
                if (temp.trim().length() > 0) {
                    contentBuilder.append(temp);
                }
                if (contentBuilder.toString().length() > 0) {
                    if (contentBuilder.toString().replaceAll("　", "").trim().length() > 0) {
                        saveDurChapterContent(md5, chapterPageIndex, title, contentBuilder.toString());
                        chapterPageIndex++;
                    }
                    contentBuilder.delete(0, contentBuilder.length());
                }
                title = line.trim().substring(line.trim().indexOf("第"));
            } else {
                if (contentBuilder.length() > 0) {
                    contentBuilder.append("\r\n\u3000\u3000").append(line);
                } else {
                    contentBuilder.append("\r\u3000\u3000").append(line);
                }
                if (title == null) {
                    title = line;
                }
            }
        }
        if (contentBuilder.length() > 0) {
            saveDurChapterContent(md5, chapterPageIndex, title, contentBuilder.toString());
            contentBuilder.delete(0, contentBuilder.length());
        }
        buffreader.close();
        inputreader.close();
        fis.close();
    }

    private void saveDurChapterContent(String md5, int chapterPageIndex, String name, String content) {
        ChapterListBean chapterListBean = new ChapterListBean();
        chapterListBean.setNoteUrl(md5);
        chapterListBean.setDurChapterIndex(chapterPageIndex);
        chapterListBean.setTag(BookShelfBean.LOCAL_TAG);
        chapterListBean.setDurChapterUrl(md5 + "_" + chapterPageIndex);
        chapterListBean.setDurChapterName(name);
        chapterListBean.getBookContentBean().setDurChapterUrl(chapterListBean.getDurChapterUrl());
        chapterListBean.getBookContentBean().setTag(BookShelfBean.LOCAL_TAG);
        chapterListBean.getBookContentBean().setNoteUrl(md5);
        chapterListBean.getBookContentBean().setDurChapterIndex(chapterListBean.getDurChapterIndex());
        chapterListBean.getBookContentBean().setDurChapterContent(content);

        DbHelper.getInstance().getmDaoSession().getBookContentBeanDao().insertOrReplace(chapterListBean.getBookContentBean());
        DbHelper.getInstance().getmDaoSession().getChapterListBeanDao().insertOrReplace(chapterListBean);
    }
}
